import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lib_uikit/lib_uikit.dart';
import 'dart:math' as math;
import 'package:lib_uikit/theme/gt_colors_v3.dart';
import 'package:lib_uikit/widgets/slider/gt_slider_v3.dart';

///刻度显示格式化
typedef ScaleFormatter = String Function(double value);

/// 修改系统主题的回调
typedef OnSliderThemeDataUpdate = SliderThemeData Function(SliderThemeData sliderThemeData);

class GTScaleSliderV3 extends ConsumerStatefulWidget {
  /// 默认值
  final double value;

  /// 左侧标签
  final String? leftLabel;

  /// 右侧标签
  final String? rightLabel;

  /// 滑动变化监听
  final ValueChanged<double>? onChanged;

  /// 滑动开始监听
  final ValueChanged<double>? onChangeStart;

  /// 滑动结束监听(手指抬起)
  final ValueChanged<double>? onChangeEnd;

  final GTSliderThemeData? sliderThemeData;

  final StateProvider<double>? sliderProvider;

  const GTScaleSliderV3(
      {Key? key,
      required this.value,
      this.onChanged,
      this.sliderThemeData,
      this.leftLabel,
      this.rightLabel,
      this.onChangeStart,
      this.onChangeEnd,
      this.sliderProvider})
      : super(key: key);

  @override
  ConsumerState<ConsumerStatefulWidget> createState() {
    return GTScaleSliderState();
  }
}

class GTScaleSliderState extends ConsumerState<GTScaleSliderV3> {
  double value = 0;
  double? initValue;

  @override
  void initState() {
    super.initState();
    value = widget.value;
  }

  bool get enabled => widget.onChanged != null;

  TextStyle get labelTextStyle =>
      TextStyle(fontSize: 16, color: enabled ? const Color(0xE6000000) : const Color(0x42000000));

  Widget get leftLabel => widget.leftLabel?.isNotEmpty == true
      ? Padding(
          padding: const EdgeInsets.only(left: 16),
          child: Text(widget.leftLabel!, style: labelTextStyle),
        )
      : Container();

  Widget get rightLabel => widget.rightLabel?.isNotEmpty == true
      ? Padding(
          padding: const EdgeInsets.only(right: 16),
          child: Text(widget.rightLabel!, style: labelTextStyle),
        )
      : Container();

  @override
  Widget build(BuildContext context) {
    var sliderThemeData = widget.sliderThemeData ?? GTSliderThemeData();
    if (value != widget.value) {
      if (initValue == null) {
        initValue = widget.value;
        value = widget.value;
      }
    }
    return Container(
      padding: const EdgeInsets.only(
        top:  8,
      ),
      child: Row(
        children: [
          leftLabel,
          if (widget.leftLabel?.isNotEmpty == true) const SizedBox(width: 8),
          Expanded(child: Consumer(builder: (context, watch, child) {
            final sliderValue = ref.watch(widget.sliderProvider as ProviderListenable);
            return SliderTheme(
              data: sliderThemeData.sliderThemeData,
              child: GTSliderV3(
                value: sliderValue,
                min: sliderThemeData.min,
                max: sliderThemeData.max,
                divisions: (sliderThemeData.max.toInt() - sliderThemeData.min.toInt()),
                marks: 5,
                onChangeStart: (value) {
                  sliderThemeData.sliderIsChanging = true;
                  if (widget.onChangeStart != null) {
                    widget.onChangeStart!(value);
                  }
                },
                onChangeEnd: (value) {
                  sliderThemeData.sliderIsChanging = false;
                  if (widget.onChangeEnd != null) {
                    widget.onChangeEnd!(value);
                  }
                },
                onChanged: enabled
                    ? (slideValue) {
                        sliderThemeData.sliderIsChanging = true;
                        if (widget.sliderProvider != null) {
                          ref.read(widget.sliderProvider!.notifier).state = slideValue;
                        }

                        setState(() {
                          value = slideValue;
                          if (widget.onChanged != null) {
                            widget.onChanged!(slideValue);
                          }
                        });
                      }
                    : null,
              ),
            );
          })),
          if (widget.rightLabel?.isNotEmpty == true) const SizedBox(width: 8),
          rightLabel
        ],
      ),
    );
  }
}

///slider显示样式配置
class GTSliderThemeData {

  /// 游标上文本样式
  final TextStyle? thumbTextStyle;

  ///disable时游标的样式
  final TextStyle disabledThumbTextStyle;

  ///刻度值的格式化
  final ScaleFormatter? scaleFormatter;

  ///刻度值的样式
  final TextStyle? scaleTextStyle;

  ///disabled状态时刻度的样式
  final TextStyle disabledScaleTextStyle;

  ///分割几块
  final int? divisions;

  ///最小值
  final double min;

  ///最大值
  final double max;

  bool? sliderIsChanging;

  /// 系统组件库
  SliderThemeData? _sliderThemeData;

  /// 上下文，用于获取主题颜色
  final BuildContext? context;

  /// 普通构建方法
  GTSliderThemeData({
    this.context,
    this.sliderIsChanging,
    this.divisions,
    this.min = 0.0,
    this.max = 1.0,
    this.scaleFormatter,
    SliderThemeData? sliderThemeData,
  })  : scaleTextStyle = gtTextStyleW400(fontSize: 12).copyWith(
      color: GTColorsV3.text6.color,
      background: Paint()
        ..color = GTColorsV3.icon5.color
        ..style = PaintingStyle.fill),
        disabledScaleTextStyle = const TextStyle(fontSize: 12, color: Colors.transparent),
        thumbTextStyle =  TextStyle(fontSize: 12, color: GTColorsV3.uikitText6V3.color),
        disabledThumbTextStyle = TextStyle(fontSize: 12, color: GTColorsV3.uikitText6V3.color),
        _sliderThemeData = sliderThemeData;

  /// 获取系统主题
  SliderThemeData get sliderThemeData {
    _sliderThemeData ??= normal();
    return _sliderThemeData!;
  }

  /// 更新系统主题
  void updateSliderThemeData(OnSliderThemeDataUpdate onSliderThemeDataUpdate) {
    _sliderThemeData = onSliderThemeDataUpdate(sliderThemeData);
  }

  /// 构建普通系统主题
  SliderThemeData normal() {
    return SliderThemeData(
      trackHeight: 2,
      activeTrackColor: GTColorsV3.uikitBrand3V3.color,
      inactiveTrackColor: GTColorsV3.uikitDivider2V3.color,
      disabledActiveTrackColor: GTColorsV3.uikitDivider2V3.color,
      disabledInactiveTrackColor: GTColorsV3.uikitDivider2V3.color,
      //可滑动圈圈stoke颜色和经过的圈圈内容色
      activeTickMarkColor: GTColorsV3.icon5.color,
      //未经过的圈圈内容色
      inactiveTickMarkColor: GTColorsV3.neutral3.color,
      disabledActiveTickMarkColor: GTColorsV3.uikitDivider2V3.color,
      disabledInactiveTickMarkColor: GTColorsV3.uikitDivider2V3.color,
      //可滑动圈圈内容色
      thumbColor: GTColorsV3.bg1.color,
      disabledThumbColor: Colors.white,
      overlayShape: const GTNoOverlayShape(),
      tickMarkShape: GTRoundSliderTickMarkShape(themeData: this, tickMarkRadius: 5),
      thumbShape: GTRoundSliderThumbShape(themeData: this),
      trackShape: const GTRoundedRectSliderTrackShape(tickMarkRadius: 7),
      rangeTickMarkShape: null,
      rangeThumbShape: null,
      rangeTrackShape: null,
      showValueIndicator: ShowValueIndicator.never,
    );
  }

  /// 复制数据，该方法配[updateSliderThemeData]可以快速服用对象属性
  GTSliderThemeData copyWith({
    SliderThemeData? themeData,
    TextStyle? disabledScaleTextStyle,
    TextStyle? disabledThumbTextStyle,
    TextStyle? scaleTextStyle,
    TextStyle? thumbTextStyle,
    int? divisions,
    double? min,
    double? max,
    ScaleFormatter? scaleFormatter,
    bool? sliderIsChanging,
  }) {
    return GTSliderThemeData(
        divisions: divisions ?? this.divisions,
        min: min ?? this.min,
        max: max ?? this.max,
        scaleFormatter: scaleFormatter ?? this.scaleFormatter,
        sliderIsChanging: sliderIsChanging ?? this.sliderIsChanging);
  }
}

///
/// Slider轨道绘制
///
class GTRoundedRectSliderTrackShape extends SliderTrackShape with BaseSliderTrackShape {
  /// Create a slider track that draws two rectangles with rounded outer edges.
  const GTRoundedRectSliderTrackShape({this.tickMarkRadius});

  /// The preferred radius of the round tick mark.
  ///
  /// If it is not provided, then 1/4 of the [SliderThemeData.trackHeight] is used.
  final double? tickMarkRadius;

  @override
  void paint(
    PaintingContext context,
    Offset offset, {
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required Animation<double> enableAnimation,
    required TextDirection textDirection,
    required Offset thumbCenter,
    Offset? secondaryOffset,
    bool isDiscrete = false,
    bool isEnabled = false,
    double additionalActiveTrackHeight = 2,
  }) {
    assert(sliderTheme.disabledActiveTrackColor != null);
    assert(sliderTheme.disabledInactiveTrackColor != null);
    assert(sliderTheme.activeTrackColor != null);
    assert(sliderTheme.inactiveTrackColor != null);
    assert(sliderTheme.thumbShape != null);
    // If the slider [SliderThemeData.trackHeight] is less than or equal to 0,
    // then it makes no difference whether the track is painted or not,
    // therefore the painting can be a no-op.
    if (sliderTheme.trackHeight == null || sliderTheme.trackHeight! <= 0) {
      return;
    }

    final activePaint = Paint()..color = GTColorsV3.uikitBrand3V3.color;
    final inactivePaint = Paint()..color = GTColorsV3.uikitDivider2V3.color;
    final Paint leftTrackPaint;
    final Paint rightTrackPaint;
    switch (textDirection) {
      case TextDirection.ltr:
        leftTrackPaint = activePaint;
        rightTrackPaint = inactivePaint;
        break;
      case TextDirection.rtl:
        leftTrackPaint = inactivePaint;
        rightTrackPaint = activePaint;
        break;
    }

    final trackRect = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    );
    final trackRadius = Radius.circular(trackRect.height / 2);
    final activeTrackRadius = Radius.circular((trackRect.height + additionalActiveTrackHeight) / 2);

    context.canvas.drawRRect(
      RRect.fromLTRBAndCorners(
        trackRect.left,
        (textDirection == TextDirection.rtl) ? trackRect.top - (additionalActiveTrackHeight / 2) : trackRect.top,
        thumbCenter.dx - (tickMarkRadius ?? 0) / 2.0,
        (textDirection == TextDirection.rtl) ? trackRect.bottom + (additionalActiveTrackHeight / 2) : trackRect.bottom,
        topLeft: (textDirection == TextDirection.ltr) ? activeTrackRadius : trackRadius,
        bottomLeft: (textDirection == TextDirection.ltr) ? activeTrackRadius : trackRadius,
      ),
      leftTrackPaint,
    );
    context.canvas.drawRRect(
      RRect.fromLTRBAndCorners(
        thumbCenter.dx + (tickMarkRadius ?? 0) / 2.0,
        (textDirection == TextDirection.rtl) ? trackRect.top - (additionalActiveTrackHeight / 2) : trackRect.top,
        trackRect.right,
        (textDirection == TextDirection.rtl) ? trackRect.bottom + (additionalActiveTrackHeight / 2) : trackRect.bottom,
        topRight: (textDirection == TextDirection.rtl) ? activeTrackRadius : trackRadius,
        bottomRight: (textDirection == TextDirection.rtl) ? activeTrackRadius : trackRadius,
      ),
      rightTrackPaint,
    );
  }
}

///
///游标的绘制
///
class GTRoundSliderThumbShape extends SliderComponentShape {
  /// Create a slider thumb that draws a circle.
  const GTRoundSliderThumbShape({
    required this.themeData,
    this.enabledThumbRadius = 5.0,
    this.disabledThumbRadius,
    this.elevation = 4.0,
    this.pressedElevation = 4.0,
  });

  /// The preferred radius of the round thumb shape when the slider is enabled.
  ///
  /// If it is not provided, then the Material Design default of 10 is used.
  final double enabledThumbRadius;

  /// The preferred radius of the round thumb shape when the slider is disabled.
  ///
  /// If no disabledRadius is provided, then it is equal to the
  /// [enabledThumbRadius]
  final double? disabledThumbRadius;

  final GTSliderThemeData themeData;

  double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius;

  /// The resting elevation adds shadow to the unpressed thumb.
  ///
  /// The default is 1.
  ///
  /// Use 0 for no shadow. The higher the value, the larger the shadow. For
  /// example, a value of 12 will create a very large shadow.
  ///
  final double elevation;

  /// The pressed elevation adds shadow to the pressed thumb.
  ///
  /// The default is 6.
  ///
  /// Use 0 for no shadow. The higher the value, the larger the shadow. For
  /// example, a value of 12 will create a very large shadow.
  final double pressedElevation;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(isEnabled == true ? enabledThumbRadius : _disabledThumbRadius);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required bool isDiscrete,
    required TextPainter labelPainter,
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required TextDirection textDirection,
    required double value,
    required double textScaleFactor,
    required Size sizeWithOverflow,
  }) {
    assert(sliderTheme.disabledThumbColor != null);
    assert(sliderTheme.thumbColor != null);
    bool isChanging = themeData.sliderIsChanging ?? false;
    final canvas = context.canvas;
    final radiusTween = Tween<double>(
      begin: _disabledThumbRadius,
      end: enabledThumbRadius,
    );
    final colorTween = ColorTween(
      begin: sliderTheme.disabledThumbColor,
      end: sliderTheme.thumbColor,
    );

    final color = colorTween.evaluate(enableAnimation)!;
    final radius = radiusTween.evaluate(enableAnimation);

    final elevationTween = Tween<double>(
      begin: elevation,
      end: pressedElevation,
    );
    var rect = sliderTheme.trackShape?.getPreferredRect(parentBox: parentBox, sliderTheme: sliderTheme);
    if (rect != null && themeData.divisions! > 0 && labelPainter.maxLines != 989 && isChanging) {
      //轨道的高度
      var trackHeight = rect.bottom - rect.top;
      //最左边的刻度中心到最右边刻度中心的长度
      var markWidth = (rect.right - rect.left) - trackHeight;
      //最左边刻度的起点
      var markStart = rect.left + trackHeight / 2;
      //每个刻度的宽度
      var perWidth = markWidth / (themeData.max - themeData.min);
      assert(perWidth > 0);
      //计算当前是第几个刻度
      var index = ((center.dx - markStart) / perWidth).round();
      //获取当前刻度的值
      var value = themeData.min + index;
      //格式化数值
      var valueFormatter = themeData.scaleFormatter != null ? themeData.scaleFormatter!(value) : value.toString();
      //绘制刻度的值
      var painter = TextPainter(
          text: TextSpan(
              text: valueFormatter,
              style: enableAnimation.value > 0 ? themeData.scaleTextStyle : themeData.disabledScaleTextStyle),
          textDirection: TextDirection.ltr,
          textAlign: TextAlign.center)
        ..layout(maxWidth: 100);

      final borderRadius = BorderRadius.circular(4.0);
      final newX = center.dx - painter.size.width / 2 - 4.0;
      final newY = center.dy - painter.height - 14 - 1;
      final newWidth = painter.size.width + 8.0;
      final newHeight = painter.size.height + 4.0;
      final newRect1 = Rect.fromLTWH(newX, newY, newWidth, newHeight);

      // 绘制圆角矩形背景
      canvas.drawRRect(
        borderRadius.toRRect(newRect1),
        themeData.scaleTextStyle!.background!,
      );

      // 计算文本绘制的位置，使其在背景矩形中居中
      final textOffsetX = newX + (newWidth - painter.width) / 2;
      final textOffsetY = newY + (newHeight - painter.height) / 2;

      // 将文本绘制在背景矩形中
      painter.paint(canvas, Offset(textOffsetX, textOffsetY));
    }
    final evaluatedElevation = elevationTween.evaluate(activationAnimation);
    final path = Path()..addArc(Rect.fromCenter(center: center, width: 2 * radius, height: 2 * radius), 0, math.pi * 2);

    var paintShadows = true;

    if (paintShadows) {
      canvas.drawShadow(path, const Color.fromRGBO(0, 0, 0, 0.5), evaluatedElevation, true);
    }
    var paint = Paint();

    paint.color = sliderTheme.activeTickMarkColor ?? GTColorsV3.uikitBrand3V3.color;
    canvas.drawCircle(center, radius + 2, paint);
    paint.color = color;
    canvas.drawCircle(
      center,
      radius,
      paint,
    );
  }
}

/// 系统用于绘制Overlay，这里不做绘制，只做slider的宽高计算
class GTNoOverlayShape extends SliderComponentShape {
  const GTNoOverlayShape();

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size(0, 40);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required bool isDiscrete,
    required TextPainter labelPainter,
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required TextDirection textDirection,
    required double value,
    required double textScaleFactor,
    required Size sizeWithOverflow,
  }) {}
}

///
/// 刻度绘制
///
class GTRoundSliderTickMarkShape extends SliderTickMarkShape {
  /// Create a slider tick mark that draws a circle.
  const GTRoundSliderTickMarkShape({
    this.tickMarkRadius,
    required this.themeData,
  });

  /// The preferred radius of the round tick mark.
  ///
  /// If it is not provided, then 1/4 of the [SliderThemeData.trackHeight] is used.
  final double? tickMarkRadius;

  final GTSliderThemeData themeData;

  @override
  Size getPreferredSize({
    required SliderThemeData sliderTheme,
    required bool isEnabled,
  }) {
    assert(sliderTheme.trackHeight != null);
    // The tick marks are tiny circles. If no radius is provided, then the
    // radius is defaulted to be a fraction of the
    // [SliderThemeData.trackHeight]. The fraction is 1/4.
    return Size.fromRadius(tickMarkRadius ?? 4);
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required Animation<double> enableAnimation,
    required TextDirection textDirection,
    required Offset thumbCenter,
    required bool isEnabled,
  }) {
    assert(sliderTheme.disabledActiveTickMarkColor != null);
    assert(sliderTheme.disabledInactiveTickMarkColor != null);
    assert(sliderTheme.activeTickMarkColor != null);
    assert(sliderTheme.inactiveTickMarkColor != null);
    // The paint color of the tick mark depends on its position relative
    // to the thumb and the text direction.
    Color? begin;
    Color? end;
    Color? markBgColor;
    switch (textDirection) {
      case TextDirection.ltr:
        final isTickMarkRightOfThumb = center.dx > thumbCenter.dx;
        begin = isTickMarkRightOfThumb
            ? sliderTheme.disabledInactiveTickMarkColor
            : sliderTheme.disabledActiveTickMarkColor;
        end = isTickMarkRightOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
        markBgColor = GTColorsV3.uikitCard2V3.color;
        break;
      case TextDirection.rtl:
        final isTickMarkLeftOfThumb = center.dx < thumbCenter.dx;
        begin =
            isTickMarkLeftOfThumb ? sliderTheme.disabledInactiveTickMarkColor : sliderTheme.disabledActiveTickMarkColor;
        end = isTickMarkLeftOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
        markBgColor = GTColorsV3.uikitCard2V3.color;
        break;
    }
    final paint = Paint()..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!;

    // The tick marks are tiny circles that are the same height as the track.
    final tickMarkRadius = getPreferredSize(
          isEnabled: isEnabled,
          sliderTheme: sliderTheme,
        ).width /
        2;
    if (tickMarkRadius > 0) {
      assert(themeData.divisions != null);
      //绘制刻度

      paint.color = markBgColor;
      Offset fixedCenter = Offset(center.dx, center.dy);
      context.canvas.drawCircle(fixedCenter, tickMarkRadius + 2, paint);
      paint.color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!;

      //绘制刻度
      context.canvas.drawCircle(fixedCenter, tickMarkRadius, paint);
    }
  }
}
